// import Widget from '../../beui/asm.js/ts/widgets/Widget'
import * as lv  from "../lvgl"

function randomWord() {
    let n = Math.round(Math.random() * 74 ) + 48
    if(n>57 && n<65) {
        n+=7
    }
    else if(n>90 && n<97) {
        n+=6
    }
    return String.fromCharCode(n)
}

export class UIModel {

    public mapWidgets: {[key:string]: lv.Obj} = {}
    public mapWidgetsByName: {[key:string]: lv.Obj} = {}

    public mapWidgetsByClass: any = {}

    public count = 0

    private insertByClass(widget: lv.Obj) {
        let className = widget.constructor.name

        if(!this.mapWidgetsByClass[className])
            this.mapWidgetsByClass[className] = {}
        this.mapWidgetsByClass[className][widget.id] = widget
    }

    public generateId(): string {
        let id = randomWord() + randomWord() + randomWord()
        while(this.mapWidgets[id]) {
            id+= randomWord()
        }
        return id
    }

    public defaultInstanceName(widget: lv.Obj): string {
        let className = widget.constructor.name

        if(!this.mapWidgetsByClass[className]) {
            this.mapWidgetsByClass[className] = []
        }
        return className.toLowerCase() + (this.mapWidgetsByClass[className].length+1)
    }

    public appendNewWidget(widget: lv.Obj) {
        if(!widget.id)
            widget.id = this.generateId()
        if(!widget.name)
            widget.name = this.defaultInstanceName(widget)

        this.mapWidgets[widget.id] = widget
        this.mapWidgetsByName[widget.name] = widget
        this.insertByClass(widget)

        this.count = Object.keys(this.mapWidgets).length
    }

    public removeWidget(id: string) {
        console.log("remove widget", id)
        let widget = this.mapWidgets[id]
        if(!widget) {
            return
        }
        if(this.mapWidgetsByClass[widget.constructor.name]) {
            delete this.mapWidgetsByClass[widget.constructor.name][id]
        }
        delete this.mapWidgets[id]
        
        this.count = Object.keys(this.mapWidgets).length
    }

    public serialize() {
        let doc: any = {
            widgets: {} ,
            disps: {} ,
        }
        for(let wid in this.mapWidgets) {
            doc.widgets[wid] = this.mapWidgets[wid].toJson()
        }
        return doc
    }
    
    public each(cb: any) {
        for(let wid in this.mapWidgets) {
            cb(this.mapWidgets[wid], wid)
        }
    }

    public widget(wid:string) {
        return this.mapWidgets[wid]
    }

    public generateSetupCode(indent=0){

        if(!Object.keys(this.mapWidgets).length)
            return ''

        let code = `${"\t".repeat(indent)}var Widget = require("besdk/ui/widget.js")\n`

        for(let wid in this.mapWidgets) {
            let wname = this.mapWidgets[wid].name
            code+= `${"\t".repeat(indent)}be.ui["${wname}"] = new Widget("${wname}")\n`
        }

        return code
    }

    public widgetSetter(widgetName:string, methodName:string, argv: any[]) {
        let widget = this.mapWidgetsByName[widgetName]
        if(!widget){
            console.error("unknow widget name", widgetName)
            return
        }
        if(!(widget as any)[methodName]){
            console.error("unknow method name", methodName)
            return
        }
        ;(widget as any)[methodName].apply(widget, argv)
    }

}